﻿using Csla;
using System;
using System.Linq;
using Csla.Serialization;
using BizControl.DalLinq;
using BizControl.Library.BusinessObjects.Activities;
using BizControl.Library.BusinessObjects.People;
using BizControl.Resources;
using BizControl.Library.Security;
using BizControl.Library.BusinessObjects.Participants;
using System.Collections.Generic;

namespace BizControl.Library.BusinessObjects.Marks
{
  [Serializable()]
  public class ActivityMarks : BusinessListBase<ActivityMarks, ActivityMarkBO>
  {
    #region  Business Methods

    private ActivityBO _activity;

    public ActivityMarkBO AddMark()
    {
      ActivityMarkBO mark = ActivityMarkBO.NewActivityMark(_activity);
      this.Add(mark);
      return mark;
    }

    public ActivityMarkBO this[Guid markSearchFor]
    {
      get
      {
        foreach (ActivityMarkBO mark in this)
        {
          if (mark.MarkId == markSearchFor)
            return mark;
        }
        return null;
      }
    }

    #endregion

    #region  Factory Methods

    internal static ActivityMarks NewActivityMarks(ActivityBO activity)
    {
      return DataPortal.CreateChild<ActivityMarks>(activity);
    }

    internal static ActivityMarks GetActivityMarks(Mark[] data, ActivityBO activity)
    {
      return DataPortal.FetchChild<ActivityMarks>(data, activity);
    }

    internal static ActivityMarks CopyMarks(ActivityBO newActivity, ActivityBO sourceActivity, 
      Dictionary<Guid, Guid> participantPairs/*, Dictionary<Guid, Guid> activityPairs*/)
    {
      var newMarks = DataPortal.CreateChild<ActivityMarks>(newActivity);
      Dictionary<Guid, Guid> markPairs = new Dictionary<Guid, Guid>();
      foreach (var mark in sourceActivity.Marks)
      {
        var newMark = newMarks.AddMark();
        newMark.Name = mark.Name;
        newMark.DueDate = mark.DueDate;
        var responsibleParticipant = newActivity.Participants[participantPairs[mark.ResponsibleParticipant.Id]];
        newMark.ResponsibleParticipant = new ParticipantInfo(responsibleParticipant);
        var nextParticipant = newActivity.Participants[participantPairs[mark.NextParticipant.Id]];
        newMark.NextParticipant = new ParticipantInfo(nextParticipant);
        newMark.Details = MarkDetails.CopyDetails(newMark, mark);
        markPairs.Add(mark.MarkId, newMark.MarkId);
      }
      foreach (var mark in sourceActivity.Marks)
      {
        var newMark = newMarks[markPairs[mark.MarkId]];
        newMark.Conditions = MarkConditions.NewMarkConditions(new MarkInfo(newMark));
        foreach (var condition in mark.Conditions)
        {
          MarkInfo newRequiredMark = null;
          ActivityInfo newRequiredActivity = null;
          if (condition.Type == ConditionType.MarkRequired)
            newRequiredMark = condition.RequiredMark == null ? null : new MarkInfo(newMarks[markPairs[condition.RequiredMark.Id]]);
          else if (condition.Type == ConditionType.SkillRequired)
            newRequiredMark = condition.RequiredMark == null ? null : new MarkInfo(condition.RequiredMark);
          //else if (condition.Type == ConditionType.ActivityRequired)
            //newRequiredActivity = new ActivityInfo(newActivity...

          newMark.Conditions.AddMarkCondition(newRequiredActivity, newRequiredMark, condition.Type);
        }
      }
      return newMarks;
    }

    private ActivityMarks()
    {
      CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ActivityMarks_CollectionChanged);
    }

    void ActivityMarks_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
      // REFACTOR
      if (_activity != null)
        _activity.HasMarks = true;
    }

    #endregion

    #region  Data Access

    private void Child_Create(ActivityBO activity)
    {
      if (null == activity) throw new ArgumentNullException(ExceptionsMessages.ActivityNullReference);
      _activity = activity;
    }

    private void Child_Fetch(Mark[] data, ActivityBO activity)
    {
      if (null == activity) throw new ArgumentNullException(ExceptionsMessages.ActivityNullReference);
      _activity = activity;
      var currentModel = SecurityChecks.GetCurrentModel();
      if (data == null) return;
      this.RaiseListChangedEvents = false;
      var checkedData = from m in data
                        where !m.IsDeleted && m.Tag == ActivityMarkBO.ActivityMarkTagName && m.Activity == activity.ActivityId
                        && m.Model == currentModel.ModelId
                        select m;
      foreach (var child in checkedData)
        Add(ActivityMarkBO.GetActivityMark(child, _activity));
      this.RaiseListChangedEvents = true;
    }

    #endregion
  }
}
